#ifndef ASTAR_H
#define ASTAR_H
#include "graph.h"
#include "edge.h"
#include <QPoint>
#include <QVector>
#include <QMap>
#include <QSet>

#include <QGraphicsItem>

#include "heuristic.h"
class AStar
{
private:

    Graph* m_graph;
    Heuristic* m_h;

    QMap<int, double > m_gscore;
    QMap<int, double > m_hscore;
    QMap<int, double > m_fscore;

    QVector<Edge* > m_cameFrom;

    QSet<int> m_openset;
    QSet<int> m_closedset;

    int m_source;
    int m_target;

public:

    QVector<Edge* > m_shortesPath;

    AStar(Graph* g, Heuristic* h):m_graph(g),m_h(h){}

    void setSource(int p)
    {
        m_source=p;
    }

    void setTarget(int p)
    {
        m_target=p;
    }

    void SearchPath();


    QVector<Edge* > newPath()
    {
        return m_shortesPath;
    }


    void ConstructPath()
    {
        m_shortesPath.clear();

        while(m_cameFrom.back()->getTo()->getIndex()!= m_target)
        {
               m_cameFrom.pop_back();
        }

        Edge* last=m_cameFrom.back();
        m_shortesPath.push_back(last);

        for(int i=m_cameFrom.size()-1; i>=0; --i)
        {
           // std::cout<<"e "<<m_cameFrom[i]->getFrom()<<" "<<m_cameFrom[i]->getTo()<<std::endl;
            if(last->getFrom()==m_cameFrom[i]->getTo())
            {
                m_shortesPath.push_front(m_cameFrom[i]);
                last=m_cameFrom[i];
            }
        }

    }
};


class Path : public QGraphicsItem
{
private:
    Graph* m_g;
public:
    QVector<Edge* > m_patch;
    Path(Graph* g):m_g(g){}

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
    {
        if(!m_patch.empty())
        {
            painter->setPen(QPen(Qt::red,3));

            foreach(Edge* ed, m_patch)
            {
                painter->drawLine(m_g->getNode(ed->getFrom()->getIndex())->getPos(),m_g->getNode(ed->getTo()->getIndex())->getPos());
            }
        }
    }

    QPointF getNodePos(int i)
    {
        return m_patch.at(i)->getTo()->getPos();
    }


    void newPath(QVector<Edge* > path)
    {
        m_patch=path;
    }

    QRectF boundingRect() const
    {
        return m_boundingRect;
    }

    void setBoundingRect(QRectF rect)
    {
        m_boundingRect=rect;
    }

protected:
    QRectF m_boundingRect;

};

#endif // ASTAR_H
